package com.mulong.common.manager.impl;

import java.math.BigDecimal;
import java.util.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.mulong.common.dao.mall.CustomerOrderDao;
import com.mulong.common.dao.mall.FinanceDao;
import com.mulong.common.domain.pojo.mall.AccountRecharge;
import com.mulong.common.domain.pojo.mall.AccountTransaction;
import com.mulong.common.domain.pojo.mall.CustomerOrderDetail;
import com.mulong.common.enums.AccountTransactionCategory;
import com.mulong.common.exception.ErrorEnums;
import com.mulong.common.exception.MulongException;
import com.mulong.common.manager.FinanceManager;
import com.mulong.common.manager.IdManager;

/**
 * FinanceManagerImpl
 * 
 * @author mulong
 * @data 2021-09-23 21:30:23
 */
@Component
public class FinanceManagerImpl implements FinanceManager {
    @Autowired
    private FinanceDao financeDao;
    @Autowired
    private CustomerOrderDao customerOrderDao;
    @Autowired
    private IdManager idManager;

    @Transactional(transactionManager = "mallTransactionManager", rollbackFor = {Exception.class, Error.class})
    @Override
    public void rechargeComplete(AccountRecharge recharge) {
        boolean rechargeCompleteResult = financeDao.rechargeComplete(recharge);
        if (!rechargeCompleteResult) {
            throw new MulongException(ErrorEnums.ACCOUNT_RECHAGRE_COMPLETE_FAILED);
        }
        Integer gatewayAccountId = recharge.getApplyGatewayAccountId();
        BigDecimal amount = recharge.getAmount();
        Date now = new Date();
        boolean increaseResult = financeDao.increaseAccountBalance(gatewayAccountId, amount);
        if (!increaseResult) {
            throw new MulongException(ErrorEnums.ACCOUNT_INCREASE_FAILED);
        }
        String transactionNo = idManager.nextAccountTransactionNo();
        String remark = "充值成功";
        AccountTransaction transaction = new AccountTransaction();
        transaction.setGatewayAccountId(gatewayAccountId);
        transaction.setTransactionNo(transactionNo);
        transaction.setTransactionCategory(AccountTransactionCategory.RECHARGE.getCode());
        transaction.setTransactionAmount(amount);
        transaction.setTransactionTime(now);
        transaction.setRemark(remark);
        financeDao.addTransaction(transaction);
    }

    @Transactional(transactionManager = "mallTransactionManager", rollbackFor = {Exception.class, Error.class})
    @Override
    public void payCustomerOrder(CustomerOrderDetail order) {
        payCustomerOrderInternal(order);
    }

    @Transactional(transactionManager = "mallTransactionManager", rollbackFor = {Exception.class, Error.class})
    @Override
    public void payCustomerOrder(List<CustomerOrderDetail> orders) {
        for (CustomerOrderDetail order : orders) {
            payCustomerOrderInternal(order);
        }
    }

    private void payCustomerOrderInternal(CustomerOrderDetail order) {
        boolean payOrderResult = customerOrderDao.pay(order);
        if (!payOrderResult) {
            throw new MulongException(ErrorEnums.CUSTOMER_ORDER_PAY_FAILED);
        }
        Integer gatewayAccountId = order.getGatewayAccountId();
        BigDecimal payPrice = order.getPayPrice();
        Date now = new Date();
        boolean decreaseResult = financeDao.decreaseAccountBalance(gatewayAccountId, payPrice);
        if (!decreaseResult) {
            throw new MulongException(ErrorEnums.ACCOUNT_DECREASE_FAILED);
        }
        String transactionNo = idManager.nextAccountTransactionNo();
        String remark = order.getOrderId();
        AccountTransaction transaction = new AccountTransaction();
        transaction.setGatewayAccountId(gatewayAccountId);
        transaction.setTransactionNo(transactionNo);
        transaction.setTransactionCategory(AccountTransactionCategory.PAYMENT.getCode());
        transaction.setTransactionAmount(payPrice);
        transaction.setTransactionTime(now);
        transaction.setRemark(remark);
        financeDao.addTransaction(transaction);
    }

}
